<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>WebSocket连接测试</title>
    <link rel="stylesheet" href="css/websocket-test.css">
</head>
<body>
    <div class="container">
        <h1>WebSocket连接测试</h1>
        <div class="notification notification-info">
            此页面用于测试WebSocket连接的建立、维护和关闭功能
        </div>

        <div class="row">
            <div class="col">
                <div class="card">
                    <h2 class="card-header">连接设置</h2>
                    <div class="form-group">
                        <label for="endpoint">WebSocket端点</label>
                        <input type="text" id="endpoint" value="/ChatMessageServer" placeholder="例如 /ChatMessageServer">
                    </div>
                    <div class="form-group">
                        <label for="username">用户名</label>
                        <input type="text" id="username" placeholder="输入用户名">
                    </div>
                    <div class="form-group">
                        <button id="connectBtn" class="btn">连接</button>
                        <button id="disconnectBtn" class="btn btn-secondary" disabled>断开</button>
                    </div>
                </div>

                <div class="card">
                    <h2 class="card-header">连接状态</h2>
                    <div class="connection-status">
                        <div id="statusIndicator" class="status-indicator status-offline"></div>
                        <span id="statusText">未连接</span>
                    </div>
                    <div class="mt-2">
                        <div>WebSocket地址: <span id="wsUrlDisplay">-</span></div>
                        <div>连接时间: <span id="connectionTime">-</span></div>
                        <div>会话ID: <span id="sessionId">-</span></div>
                    </div>
                </div>
            </div>

            <div class="col">
                <div class="card">
                    <h2 class="card-header">发送测试消息</h2>
                    <div class="form-group">
                        <label for="testMessageType">消息类型</label>
                        <select id="testMessageType">
                            <option value="ping">Ping消息</option>
                            <option value="echo">回显消息</option>
                            <option value="system">系统消息</option>
                            <option value="custom">自定义消息</option>
                        </select>
                    </div>

                    <div class="form-group" id="customMsgDiv">
                        <label for="customMessage">自定义消息 (JSON)</label>
                        <textarea id="customMessage" rows="5">{"type": "custom", "content": "这是一个测试消息"}</textarea>
                    </div>

                    <div class="form-group">
                        <button id="sendTestBtn" class="btn" disabled>发送测试消息</button>
                    </div>
                </div>

                <div class="card">
                    <h2 class="card-header">连接日志</h2>
                    <div id="connectionLogs" class="message-list"></div>
                    <div class="mt-2">
                        <button id="clearLogsBtn" class="btn btn-secondary">清空日志</button>
                    </div>
                </div>
            </div>
        </div>

        <div class="row mt-3">
            <div class="col">
                <div class="card">
                    <h2 class="card-header">网络诊断</h2>
                    <div class="form-group">
                        <button id="diagnosticBtn" class="btn">运行网络诊断</button>
                    </div>
                    <div id="diagnosticResults" class="mt-2"></div>
                </div>
            </div>
            <div class="col">
                <div class="card">
                    <h2 class="card-header">重连测试</h2>
                    <div class="form-group">
                        <label>模拟连接断开</label>
                        <button id="simulateDisconnectBtn" class="btn btn-secondary" disabled>模拟断开</button>
                    </div>
                    <div class="form-group">
                        <label for="maxReconnectAttempts">最大重连次数</label>
                        <input type="number" id="maxReconnectAttempts" value="5" min="1" max="10">
                    </div>
                    <div class="form-group">
                        <label for="reconnectInterval">重连间隔 (毫秒)</label>
                        <input type="number" id="reconnectInterval" value="3000" min="1000" max="10000" step="1000">
                    </div>
                </div>
            </div>
        </div>
    </div>

    <!-- 脚本引入 -->
    <script src="js/websocket-client.js"></script>
    <script>
    // DOM元素
    const connectBtn = document.getElementById('connectBtn');
    const disconnectBtn = document.getElementById('disconnectBtn');
    const endpointInput = document.getElementById('endpoint');
    const usernameInput = document.getElementById('username');
    const statusIndicator = document.getElementById('statusIndicator');
    const statusText = document.getElementById('statusText');
    const wsUrlDisplay = document.getElementById('wsUrlDisplay');
    const connectionTime = document.getElementById('connectionTime');
    const sessionId = document.getElementById('sessionId');
    const connectionLogs = document.getElementById('connectionLogs');
    const clearLogsBtn = document.getElementById('clearLogsBtn');
    const sendTestBtn = document.getElementById('sendTestBtn');
    const testMessageType = document.getElementById('testMessageType');
    const customMessageTextarea = document.getElementById('customMessage');
    const customMsgDiv = document.getElementById('customMsgDiv');
    const diagnosticBtn = document.getElementById('diagnosticBtn');
    const diagnosticResults = document.getElementById('diagnosticResults');
    const simulateDisconnectBtn = document.getElementById('simulateDisconnectBtn');
    const maxReconnectAttemptsInput = document.getElementById('maxReconnectAttempts');
    const reconnectIntervalInput = document.getElementById('reconnectInterval');

    // 变量
    let wsClient = null;
    let connectionStartTime = null;
    let connectionTimer = null;

    // 页面初始化
    function init() {
        // 从URL参数获取用户名和端点
        const urlParams = new URLSearchParams(window.location.search);
        if (urlParams.has('username')) {
            usernameInput.value = urlParams.get('username');
        }
        if (urlParams.has('endpoint')) {
            endpointInput.value = urlParams.get('endpoint');
        }

        // 隐藏自定义消息表单
        testMessageType.addEventListener('change', function() {
            customMsgDiv.style.display = this.value === 'custom' ? 'block' : 'none';
        });
        customMsgDiv.style.display = 'none';

        // 绑定事件
        connectBtn.addEventListener('click', connect);
        disconnectBtn.addEventListener('click', disconnect);
        clearLogsBtn.addEventListener('click', clearLogs);
        sendTestBtn.addEventListener('click', sendTestMessage);
        diagnosticBtn.addEventListener('click', runDiagnostic);
        simulateDisconnectBtn.addEventListener('click', simulateDisconnect);
    }

    // 连接WebSocket
    function connect() {
        const endpoint = endpointInput.value.trim();
        const username = usernameInput.value.trim();

        if (!endpoint) {
            addLog('错误', 'WebSocket端点不能为空');
            return;
        }

        if (!username) {
            addLog('错误', '用户名不能为空');
            return;
        }

        // 禁用连接按钮
        connectBtn.disabled = true;
        addLog('信息', `尝试连接到 ${endpoint}...`);

        try {
            // 创建WebSocket客户端
            wsClient = new WebSocketClient(endpoint, username, {
                onConnect: handleConnect,
                onDisconnect: handleDisconnect,
                onMessage: handleMessage,
                onError: handleError,
                onReconnect: handleReconnect,
                onReconnectFailed: handleReconnectFailed
            });

            // 设置重连参数
            wsClient.maxReconnectAttempts = parseInt(maxReconnectAttemptsInput.value) || 5;
            wsClient.reconnectInterval = parseInt(reconnectIntervalInput.value) || 3000;

            // 连接
            wsClient.connect();
        } catch (error) {
            addLog('错误', `连接初始化失败: ${error.message}`);
            connectBtn.disabled = false;
        }
    }

    // 处理连接成功
    function handleConnect() {
        // 更新UI状态
        statusIndicator.className = 'status-indicator status-online';
        statusText.textContent = '已连接';
        wsUrlDisplay.textContent = wsClient.getWebSocketUrl(wsClient.endpoint);
        connectBtn.disabled = true;
        disconnectBtn.disabled = false;
        sendTestBtn.disabled = false;
        simulateDisconnectBtn.disabled = false;
        
        // 记录连接时间
        connectionStartTime = new Date();
        updateConnectionTime();
        connectionTimer = setInterval(updateConnectionTime, 1000);

        // 生成会话ID (这里只是模拟)
        sessionId.textContent = wsClient.generateUUID();

        addLog('成功', '连接已建立');
    }

    // 处理连接断开
    function handleDisconnect(event) {
        // 更新UI状态
        statusIndicator.className = 'status-indicator status-offline';
        statusText.textContent = '已断开';
        disconnectBtn.disabled = true;
        sendTestBtn.disabled = true;
        simulateDisconnectBtn.disabled = true;
        
        // 停止连接时间定时器
        if (connectionTimer) {
            clearInterval(connectionTimer);
            connectionTimer = null;
        }

        addLog('信息', `连接已断开${event.code ? (' (代码: ' + event.code + ')') : ''}`);
    }

    // 处理接收消息
    function handleMessage(message) {
        addLog('接收', JSON.stringify(message, null, 2));
    }

    // 处理错误
    function handleError(error) {
        addLog('错误', error.message || '发生未知错误');
    }

    // 处理重连尝试
    function handleReconnect(attempt, maxAttempts) {
        statusText.textContent = `正在重连 (${attempt}/${maxAttempts})`;
        statusText.className = 'animate-blink';
        addLog('信息', `尝试重连 (${attempt}/${maxAttempts})...`);
    }

    // 处理重连失败
    function handleReconnectFailed() {
        statusText.textContent = '重连失败';
        statusText.className = '';
        connectBtn.disabled = false;
        addLog('错误', '重连失败，已达到最大尝试次数');
    }

    // 主动断开连接
    function disconnect() {
        if (wsClient) {
            wsClient.disconnect();
            connectBtn.disabled = false;
        }
    }

    // 发送测试消息
    function sendTestMessage() {
        if (!wsClient || !wsClient.connected) {
            addLog('错误', '未连接到WebSocket服务器');
            return;
        }

        const type = testMessageType.value;
        let message;

        switch (type) {
            case 'ping':
                message = {
                    type: 'system',
                    fromUser: wsClient.username,
                    toUser: 'server',
                    contentType: 'text',
                    content: 'PING'
                };
                break;
            case 'echo':
                message = {
                    type: 'chat',
                    fromUser: wsClient.username,
                    toUser: wsClient.username,
                    contentType: 'text',
                    content: 'Echo test message'
                };
                break;
            case 'system':
                message = {
                    type: 'system_notification',
                    fromUser: wsClient.username,
                    contentType: 'text',
                    content: '系统测试消息'
                };
                break;
            case 'custom':
                try {
                    message = JSON.parse(customMessageTextarea.value);
                } catch (error) {
                    addLog('错误', `无效的JSON格式: ${error.message}`);
                    return;
                }
                break;
        }

        wsClient.send(message);
        addLog('发送', JSON.stringify(message, null, 2));
    }

    // 更新连接时间
    function updateConnectionTime() {
        if (!connectionStartTime) return;
        
        const now = new Date();
        const diff = now - connectionStartTime;
        let seconds = Math.floor(diff / 1000);
        let minutes = Math.floor(seconds / 60);
        let hours = Math.floor(minutes / 60);
        
        seconds %= 60;
        minutes %= 60;
        
        connectionTime.textContent = `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
    }

    // 添加日志
    function addLog(level, message) {
        const logItem = document.createElement('div');
        logItem.className = 'message-item animate-fade-in';
        
        const timeStr = new Date().toLocaleTimeString();
        let levelClass = '';
        
        switch (level.toLowerCase()) {
            case '错误':
                levelClass = 'text-danger';
                break;
            case '成功':
                levelClass = 'text-success';
                break;
            case '信息':
                levelClass = 'text-muted';
                break;
            default:
                levelClass = '';
        }
        
        logItem.innerHTML = `
            <div class="message-header">
                <span class="message-sender ${levelClass}">[${level}]</span>
                <span class="message-time">${timeStr}</span>
            </div>
            <div class="message-content">${message}</div>
        `;
        
        connectionLogs.appendChild(logItem);
        connectionLogs.scrollTop = connectionLogs.scrollHeight;
    }

    // 清空日志
    function clearLogs() {
        connectionLogs.innerHTML = '';
    }

    // 运行网络诊断
    function runDiagnostic() {
        diagnosticResults.innerHTML = '<div class="notification notification-info">正在运行网络诊断...</div>';
        
        // 测试WebSocket支持
        let results = '<h3>网络诊断结果</h3>';
        results += '<ul>';
        
        // 检查WebSocket支持
        if ('WebSocket' in window) {
            results += '<li>✅ 浏览器支持WebSocket</li>';
        } else {
            results += '<li>❌ 浏览器不支持WebSocket</li>';
        }
        
        // 检查SSL
        const isSecure = window.location.protocol === 'https:';
        results += `<li>${isSecure ? '✅' : '⚠️'} 当前页面${isSecure ? '使用' : '未使用'}安全连接 (HTTPS)</li>`;
        
        // 检查网络连接
        results += '<li>检查网络连接: ';
        if (navigator.onLine) {
            results += '✅ 在线</li>';
        } else {
            results += '❌ 离线</li>';
        }
        
        // 检查端点有效性
        const endpoint = endpointInput.value.trim();
        if (endpoint) {
            if (endpoint.startsWith('/') || endpoint.startsWith('ws://') || endpoint.startsWith('wss://')) {
                results += '<li>✅ 端点格式有效</li>';
            } else {
                results += '<li>⚠️ 端点格式可能无效 (应以 / 开头或使用完整的 ws:// 或 wss:// URL)</li>';
            }
        } else {
            results += '<li>❌ 未提供端点</li>';
        }
        
        results += '</ul>';
        
        diagnosticResults.innerHTML = results;
        
        // 尝试发送一次ping检测
        if (wsClient && wsClient.connected) {
            addLog('信息', '发送诊断ping测试');
            
            // 记录开始时间
            const pingStart = Date.now();
            
            wsClient.send({
                type: 'system',
                fromUser: wsClient.username,
                toUser: 'server',
                contentType: 'text',
                content: 'DIAGNOSTIC_PING',
                timestamp: pingStart
            });
            
            // 5秒后检查是否收到回应
            setTimeout(() => {
                // 这里简单模拟一个回应，实际应该检查是否收到真实回应
                const pingTime = Math.floor(Math.random() * 100) + 10;
                addLog('信息', `诊断ping测试完成: ${pingTime}ms`);
                
                diagnosticResults.innerHTML += `
                    <div class="mt-2">
                        <h4>延迟测试</h4>
                        <p>Round-trip time: ${pingTime}ms</p>
                    </div>
                `;
            }, 1000);
        }
    }
    
    // 模拟连接断开
    function simulateDisconnect() {
        if (!wsClient || !wsClient.connected) {
            addLog('错误', '未连接到WebSocket服务器');
            return;
        }
        
        addLog('信息', '模拟连接断开');
        
        // 简单的模拟断开方式是关闭socket但不设置手动断开标记
        wsClient.socket.close(4999, '模拟断开');
    }

    // 初始化页面
    document.addEventListener('DOMContentLoaded', init);
    </script>
</body>
</html> 